﻿using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Sidvall.Tasks
{
	public sealed class MonitoredTaskCollection : System.Collections.ObjectModel.KeyedCollection<string, IMonitoredTask>
	{
		#region Public Members

		#region AddRange

		public void AddRange(IEnumerable<IMonitoredTask> items)
		{
			if (items == null)
				return;
			foreach (var item in items)
			{
				if ((item != null) && (!Contains(item.TaskId)))
					Add(item);
			}
		}

		#endregion
		#region ExecuteAsync

		public async Task ExecuteAsync(System.IProgress<MonitoredTaskProgress> progress, CancellationToken cancellationToken)
		{
			foreach (var item in this)
				await item.ExecuteAsync(progress, cancellationToken).ConfigureAwait(false);
		}

		#endregion
		#region ExecuteAsOneAsync

		public async Task ExecuteAsOneAsync(System.IProgress<MonitoredTaskProgress> progress, CancellationToken cancellationToken)
		{
			var items = GetTasks(progress, cancellationToken);

			await Task.WhenAll(items).ConfigureAwait(false);
		}

		#endregion

		#region GetKeyForItem

		protected override string GetKeyForItem(IMonitoredTask item)
		{
			if (item == null)
				throw new System.ArgumentNullException(nameof(item));
			return item.TaskId;
		}

		#endregion

		#endregion
		#region Private Members

		#region GetTasks

		private List<Task> GetTasks(System.IProgress<MonitoredTaskProgress> progress, CancellationToken cancellationToken)
		{
			var items = new List<Task>();
			foreach (var item in this)
				items.Add(item.ExecuteAsync(progress, cancellationToken));
			return items;
		}

		#endregion

		#endregion
	}
}
